"""
(1) 题目描述：
通过OpenCV读取一张图片，完成下面的操作
"""

# (2) 题目要求：.
# ①　导入相关头文件
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

spr = 2
spc = 3
spn = 0
plt.figure(figsize=[12, 6])


def my_show_img(img, title, trans=None, **kwargs):
    global spn
    spn += 1
    plt.subplot(spr, spc, spn)
    plt.title(title)
    plt.axis('off')
    if trans is not None:
        img = trans(img)
    plt.imshow(img, **kwargs)


# ②　读入一张图片并转为灰度图
path = 'data/car_id.png'
gray = cv.imread(path, cv.IMREAD_GRAYSCALE)
my_show_img(gray, 'gray', cmap='gray')

# ③　将图像转变为二值图
ret, bin = cv.threshold(gray, 0, 255, cv.THRESH_OTSU + cv.THRESH_BINARY)
my_show_img(bin, 'bin', cmap='gray')

# ④　自定义开运算的核
kernel = np.ones((3, 3), dtype=np.uint8)

# ⑤　完成开运算
opening = cv.morphologyEx(bin, cv.MORPH_OPEN, kernel, iterations=2)
my_show_img(opening, 'opening', cmap='gray')

# ⑥　对二值图进行反转
inv = cv.bitwise_not(bin)
my_show_img(inv, 'inv', cmap='gray')

# ⑦　自定义闭运算的核
kernel = np.ones((3, 3), dtype=np.uint8)

# ⑧　完成闭运算
# ⑨　完成结果正确
closing = cv.morphologyEx(bin, cv.MORPH_CLOSE, kernel, iterations=1)
my_show_img(closing, 'closing', cmap='gray')

# ⑩　提取轮廓
contours, _ = cv.findContours(closing, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# 11　设置轮廓的宽高比进行车牌的筛选
ratio = 2.
char_arr = []
for c in contours:
    rect = cv.boundingRect(c)
    x, y, w, h = rect
    if not np.isclose(ratio, float(h) / w, atol=0.25):
        continue
    char_arr.append(rect)

# 12　提取车牌，并保存
first = True
char_w, char_h = 50, 100
char_size = (char_w, char_h)
pts2 = np.float32(((0, 0), (char_w, 0), (char_w, char_h)))
char_affine_arr = []
left_side_arr = []
for rect in char_arr:
    x, y, w, h = rect
    left_side_arr.append(x)
    pts1 = np.float32(((x,y), (x + w, y), (x + w, y + h)))
    M = cv.getAffineTransform(pts1, pts2)
    affine = cv.warpAffine(gray, M, char_size)
    char_affine_arr.append(affine)
char_affine_arr = np.uint8(char_affine_arr)
left_side_arr = np.int32(left_side_arr)
idx_ordered = left_side_arr.argsort()
char_affine_arr = char_affine_arr[idx_ordered]
res = np.concatenate(char_affine_arr, axis=1)
my_show_img(res, 'res', cmap='gray')

# 13　加入必要注释

plt.show()
